package com.xuxu.controller;

import com.xuxu.pojo.Stu;
import com.xuxu.dao.StuDao;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.search.MultiMatchQuery;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;
import java.util.Optional;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")   //加载配置文件
public class ElasticSearchTest {

    //注入ElasticSearchTemplate
    @Autowired
    private ElasticsearchTemplate template;

    @Autowired
    private StuDao stuDao;


    /**
     * 创建索引
     */
    @Test
    public void createIndex() {
        //参数是 实体类的字节码文件
        //他会根据实体类的信息，自动创建索引信息,el的版本在6.1.2以上才可以
        template.createIndex(Stu.class);
        //创建映射
        //template.putMapping(Stu.class);
    }

    /**
     * 创建文档，既是创建也是更新
     */
    @Test
    public void addDocument() {
        Stu stu = new Stu();
        stu.setId(1L);
        stu.setName("俄罗斯政治评论家波罗热科认为");
        stu.setAddress("中国政府和人民在抗击新冠肺炎疫情方面表现出高度团结，各项工作开展得有条不紊。" +
                "在中国共产党领导下，中国在最短时间内集中最大力量抗击疫情");
        //保存这条数据到 域中
        stuDao.save(stu);
    }

    /**
     * 查询文档
     */
    @Test
    public void query() {
        //查询所有的记录
        Iterable<Stu> stus = stuDao.findAll();

        for (Stu stu : stus) {
            System.out.println(stu);
        }
    }

    /**
     * 根据id删除记录
     */
    @Test
    public void delete() {
        //根据id删除
        stuDao.deleteById(1L);
    }


    /**
     * 根据id查询
     */
    @Test
    public void findById() {
        //返回值是一个Optional对象，这个对象差不多就是实体类，不过是封装的，里面封装 判断返回是否有值
        Optional<Stu> byId = stuDao.findById(1L);
        //判断查询出来的对象是否有值
        if (byId.isPresent()) {
            //获取查询出来的对象
            Stu stu = byId.get();
            System.out.println(stu);
        } else {
            System.out.println("数据为空");
        }
    }


    /**
     * 添加100个数据到索引中
     */
    @Test
    public void addDocument100() {

        Stu stu = new Stu();

        for (Long i = 0L; i < 100L; i++) {
            //准备一个stu对象，设置属性
            stu.setId(i + 1);
            stu.setName("苹果iPhone SE 2最新渲染图曝光：6色可选" + (i + 1));
            stu.setAddress((i + 1) + "此次曝光的iPhone SE 2共有6种配色，这组渲染图的制作者称其结合了现有关于iPhone SE 2的信息。从渲染图来看，样机依旧沿用了iPhone 8的设计思路，采用后置单摄方案，玻璃后盖设计以及金属边框。");
            stuDao.save(stu);
        }
    }


    /**
     * 分页查询
     */
    @Test
    public void findByPage() {
        //首先定于一个分页对象，然后设置页码(页码索引是从0开始)，设置每页显示的条数
//        Pageable pageable = PageRequest.of(5,10);
        Pageable pageable = new PageRequest(0, 10);

        Page<Stu> page = stuDao.findAll(pageable);

        for (Stu stu : page) {
            System.out.println(stu);
        }

        System.out.println("总页数是：" + page.getTotalPages());
        System.out.println("总记录数是：" + page.getTotalElements());
        System.out.println("每页显示的记录数：" + page.getSize());
    }


    /**
     * 分页查询 + 排序
     * <p>
     * 注意使用排序的时候，需要在实体类的 @Field注解 上面加一个 fielddata = true，这样才可以实现排序
     */
    @Test
    public void findByPageAndSort() {
        //准备一个排序对象, 设置排序方法asc()升序，desc()降序，并且指定是按照什么排序的   id
        Sort sort = Sort.by(Sort.Order.desc("id"));
        //准备一个分页对象
        Pageable pageable = PageRequest.of(0, 12, sort);
        //调用dao层的方法进行分页查询
        Page<Stu> page = stuDao.findAll(pageable);

        System.out.println("总页数是：" + page.getTotalPages());
        System.out.println("总记录数是：" + page.getTotalElements());
        System.out.println("每页显示的记录数：" + page.getSize());
        System.out.println("排序的方式是" + page.getSort().toString());

        for (Stu stu : page) {
            System.out.println(stu);
        }
    }


    /**
     * 自定义查询,根据名称查询
     * 在dao层的接口中继承了ElasticsearchRepository<>这个类 ,但是只能提供最简单的CRUD，
     * 如果有其他的需求，需要去接口中自定义方法，只用写抽象方法，不用写实现，写的时候要注意规范
     */
    @Test
    public void findByName(){
        //根据name字段查询
        //List<Stu> stuList = stuDao.findByName("20");

        //根据address字段查询
        List<Stu> stuList  = stuDao.findByNameOrAddress("苹果12","玻璃11");

        for (Stu stu : stuList) {
            System.out.println(stu);
        }
        System.out.println("一共有： "+stuList.size());
    }


    /**
     * 使用原生对象查询
     * 使用原生查询使用的对象是 template模版的形式，不是使用dao接口
     */
    @Test
    public void findByNativeQuery(){
        //准备一个分页对象，实现类是PageRequest,参数是 当前页码(从0开始)，每页显示的条数，如果需要排序 查看上面的排序方法
        Pageable pageable = PageRequest.of(0,9);
        //创建一个 原生的查询对象，使用withPageable(分页对象)  .build()
        SearchQuery quert = new NativeSearchQueryBuilder().withPageable(pageable).build();

        //使用template对象调用queryForList方法，进行分页查询
        List<Stu> stuList = template.queryForList(quert, Stu.class);

        for (Stu stu : stuList) {
            System.out.println(stu);
        }

    }





}
